"""
Conditional routing implementation
"""
from typing import Callable, Dict, List, Optional, Tuple
from ...core.message import Message

class RouteCondition:
    """路由条件类"""
    
    def __init__(self, condition: Callable[[Message], bool], target: str, description: str = ""):
        """
        初始化路由条件
        Args:
            condition: 条件判断函数，接收Message对象返回bool
            target: 满足条件时的目标代理ID
            description: 条件描述（用于可视化和调试）
        """
        self.condition = condition
        self.target = target
        self.description = description or "Custom condition"
        
    def evaluate(self, message: Message) -> bool:
        """
        评估条件是否满足
        Args:
            message: 待评估的消息
        Returns:
            条件是否满足
        """
        try:
            return self.condition(message)
        except Exception as e:
            # 条件评估出错时返回False
            print(f"Error evaluating condition: {str(e)}")
            return False

class ConditionalRouter:
    """条件路由器"""
    
    def __init__(self):
        # {source_agent: [(condition, target)]}
        self.conditions: Dict[str, List[RouteCondition]] = {}
        
    def add_condition(self, source: str, condition: Callable[[Message], bool], 
                     target: str, description: str = "") -> None:
        """
        添加条件路由规则
        Args:
            source: 源代理 ID
            condition: 条件函数
            target: 目标代理 ID
            description: 条件描述
        """
        if source not in self.conditions:
            self.conditions[source] = []
            
        route_condition = RouteCondition(condition, target, description)
        self.conditions[source].append(route_condition)
        
    def get_conditional_target(self, message: Message) -> Optional[str]:
        """
        根据条件确定消息的目标代理
        Args:
            message: 消息对象
        Returns:
            满足条件的目标代理 ID，如果没有满足的条件则返回None
        """
        if message.sender not in self.conditions:
            return None
            
        # 按添加顺序评估条件，返回第一个满足的条件对应的目标
        for condition in self.conditions[message.sender]:
            if condition.evaluate(message):
                return condition.target
                
        return None
        
    def get_conditions_for_agent(self, agent_id: str) -> List[Tuple[str, str]]:
        """
        获取指定代理的所有条件规则
        Args:
            agent_id: 代理 ID
        Returns:
            条件描述和目标的列表 [(description, target)]
        """
        if agent_id not in self.conditions:
            return []
            
        return [(cond.description, cond.target) for cond in self.conditions[agent_id]]
        
    def clear_conditions(self, agent_id: Optional[str] = None) -> None:
        """
        清除条件规则
        Args:
            agent_id: 要清除的代理ID，None表示清除所有规则
        """
        if agent_id is None:
            self.conditions.clear()
        elif agent_id in self.conditions:
            self.conditions[agent_id].clear()
            
    def get_all_targets(self) -> set[str]:
        """
        获取所有可能的目标代理ID
        Returns:
            目标代理ID集合
        """
        targets = set()
        for conditions in self.conditions.values():
            for condition in conditions:
                targets.add(condition.target)
        return targets
        
class CommonConditions:
    """预定义的常用条件"""
    
    @staticmethod
    def content_contains(keyword: str) -> Callable[[Message], bool]:
        """
        创建检查消息内容是否包含关键词的条件
        Args:
            keyword: 关键词
        Returns:
            条件函数
        """
        def condition(message: Message) -> bool:
            return keyword.lower() in str(message.content).lower()
        return condition
        
    @staticmethod
    def message_type_is(msg_type: str) -> Callable[[Message], bool]:
        """
        创建检查消息类型的条件
        Args:
            msg_type: 消息类型
        Returns:
            条件函数
        """
        def condition(message: Message) -> bool:
            return message.type.name == msg_type
        return condition
        
    @staticmethod
    def has_metadata(key: str, value: Optional[any] = None) -> Callable[[Message], bool]:
        """
        创建检查消息元数据的条件
        Args:
            key: 元数据键
            value: 可选的期望值
        Returns:
            条件函数
        """
        def condition(message: Message) -> bool:
            if not message.metadata or key not in message.metadata:
                return False
            if value is None:
                return True
            return message.metadata[key] == value
        return condition
